﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;

namespace ECommon
{
    /// <summary>
    /// 串口创建工具
    /// </summary>
    public static class SerialPortTool
    {
        /// <summary>
        /// 串口名选项
        /// </summary>
        public static readonly List<string> PortNameOptions = (SerialPort.GetPortNames() == null ? new List<string>() : SerialPort.GetPortNames().ToList());

        /// <summary>
        /// 波特率选项
        /// </summary>
        public static readonly List<string> BaudRateOptions = new List<string>() { "115200", "76800", "38400", "19200", "9600", "4800", "2400" };

        /// <summary>
        /// 数据位选项
        /// </summary>
        public static readonly List<string> DataBitOptions = new List<string> { "8", "7", "6", "5" };

        /// <summary>
        /// 停止位选项
        /// </summary>
        public static readonly List<string> StopBitOptions = new List<string> { "1", "1.5", "2", "无" };

        /// <summary>
        /// 校验位选项
        /// </summary>
        public static readonly List<string> ParityOptions = new List<string> { "无校验", "奇校验", "偶校验", "0校验", "1校验" };

        /// <summary>
        /// 创建串口
        /// </summary>
        /// <param name="portName">串口名称</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBit">数据位</param>
        /// <param name="stopBit">停止位</param>
        /// <param name="parity">校验位</param>
        /// <returns>串口</returns>
        /// <exception cref="Exception">串口参数错误异常</exception>
        public static SerialPort Create(string portName, string baudRate, string dataBit, string stopBit, string parity)
        {
            string[] ports = SerialPort.GetPortNames();
            if (ports == null || ports.Length <= 0)
            {
                throw new Exception("未发现串口");
            }
            if (!ports.ToList().Exists(a => a.ToLower().Contains(portName.ToLower())))
            {
                throw new Exception(string.Format("错误的串口名：{0}，其值必须为{1}之一", portName, string.Join(", ", ports)));
            }

            if (!BaudRateOptions.Contains(baudRate))
            {
                throw new Exception(string.Format("错误的比特率：{0}，其值必须为{1}之一", baudRate, string.Join(", ", BaudRateOptions.ToArray())));
            }
            int baudRateTmp = int.Parse(baudRate);
            if (!DataBitOptions.Contains(dataBit))
            {
                throw new Exception(string.Format("错误的数据位：{0}，其值必须为{1}之一", dataBit, string.Join(", ", DataBitOptions.ToArray())));
            }
            int dataBitTmp = int.Parse(dataBit);
            StopBits stopBitTmp = StopBits.None;
            switch (stopBit)
            {
                case "1":
                    stopBitTmp = StopBits.One;
                    break;

                case "1.5":
                    stopBitTmp = StopBits.OnePointFive;
                    break;

                case "2":
                    stopBitTmp = StopBits.Two;
                    break;

                case "无":
                    stopBitTmp = StopBits.None;
                    break;

                default:
                    throw new Exception(string.Format("错误的停止位：{0}，其值必须为{1}之一", stopBit, string.Join(", ", StopBitOptions.ToArray())));
            }
            Parity parityTmp = Parity.None;
            switch (parity)
            {
                case "奇校验":
                    parityTmp = Parity.Odd;
                    break;

                case "偶校验":
                    parityTmp = Parity.Even;
                    break;

                case "0校验":
                    parityTmp = Parity.Space;
                    break;

                case "1校验":
                    parityTmp = Parity.Mark;
                    break;

                case "无校验":
                    parityTmp = Parity.None;
                    break;

                default:
                    throw new Exception(string.Format("错误的校验位：{0}，其值必须为{1}之一", parity, string.Join(", ", ParityOptions.ToArray())));
            }
            return new SerialPort(portName, baudRateTmp, parityTmp, dataBitTmp, stopBitTmp);
        }
    }
}